package com.awakening.Bootstrap;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.oio.OioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.channel.socket.oio.OioDatagramChannel;
import io.netty.channel.socket.oio.OioSocketChannel;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.util.AttributeKey;

import java.net.DatagramPacket;
import java.net.InetSocketAddress;
import java.util.concurrent.Future;

/**
 * @Author:AwakeningCode
 * @Date: Created in 20:22 2018\3\7 0007
 */
public class Test {

    public static void main(String[] args) throws Exception{

        /*EventLoopGroup group = new NioEventLoopGroup();
        //创建一个Bootstrap类的实例以创建和连接新的客户端Channel
        Bootstrap bootstrap = new Bootstrap();
        //设置EventLoopGroup，提供用于处理Channel事件的EventLoop
        bootstrap.group(group)
                //指定要使用的Channel实现
                .channel(NioSocketChannel.class)
                //指定用于Channel事件和数据的ChannelInboundHandler
                .handler(new SimpleChannelInboundHandler<ByteBuf>() {
                    @Override
                    protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf)
                            throws Exception {
                        System.out.println("Received data");
                    }
                });
        ChannelFuture future = bootstrap.connect(
                //连接到远程主机
                new InetSocketAddress("www.myself.com",80)
        );
        future.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture channelFuture) throws Exception {
                if (channelFuture.isSuccess()){
                    System.out.println("Connection established");
                } else {
                    System.out.println("Connection attempt failed");
                    channelFuture.cause().printStackTrace();
                }
            }
        });*/


        /*EventLoopGroup group = new NioEventLoopGroup();
        //创建一个Bootstrap类的实例以创建和连接新的客户端Channel
        Bootstrap bootstrap = new Bootstrap();
        //指定一个适用于OIO的Channel实现类
        bootstrap.group(group)
                .channel(OioSocketChannel.class)
                //设置一个用于处理Channel的I/O事件和数据的ChannelInboundHandler
                .handler(new SimpleChannelInboundHandler<ByteBuf>() {
                    @Override
                    protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf)
                            throws Exception {
                        System.out.println("Received data");
                    }
                });
        ChannelFuture future = bootstrap.connect(
                //尝试连接到远程节点
            new InetSocketAddress("www.myself.com",80)
        );
        future.syncUninterruptibly();*/

        /*NioEventLoopGroup group = new NioEventLoopGroup();
        //创建ServerBootstrap
        ServerBootstrap bootstrap = new ServerBootstrap();
        //设置EventLoopGroup，其提供了用于处理Channel事件的EventLoop
        bootstrap.group(group)
                //指定要使用的Channel实现
                .channel(NioServerSocketChannel.class)
                .childHandler(new SimpleChannelInboundHandler<ByteBuf>() {
                    @Override
                    protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf)
                            throws Exception {
                        System.out.println("Received data");
                    }
                });
        //通过配置好的ServerBootstrap的实例绑定该Channel
        ChannelFuture future = bootstrap.bind(new InetSocketAddress(8080));
        future.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture channelFuture) throws Exception {
                if (channelFuture.isSuccess()){
                    System.out.println("Server bound");
                } else {
                    System.out.println("Bound attempt failed");
                    channelFuture.cause().printStackTrace();
                }
            }
        });*/


        /*//创建ServerBootstrap以创建和绑定新的Channel
        ServerBootstrap bootstrap = new ServerBootstrap();
        //设置EventLoopGroup，其将提供用以处理Channel事件的EventLoop
        bootstrap.group(new NioEventLoopGroup(),new NioEventLoopGroup())
                //指定Channel的实现
                .channel(NioServerSocketChannel.class)
                //注册一个ChannelInitializerImpl的实例来设置ChannelPipeline
                .childHandler(new ChannelInitializerImpl());
        ChannelFuture future = bootstrap.bind(new InetSocketAddress(8080));
        future.sync();*/

        /*//创建一个AttributeKey以标识该属性
        final AttributeKey<Integer> id = AttributeKey.valueOf("ID");
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(new NioEventLoopGroup())
                .channel(NioSocketChannel.class)
                .handler(new SimpleChannelInboundHandler<ByteBuf>() {
                    @Override
                    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
                        //使用AttributeKey检索属性以及它的值
                        Integer idValue = ctx.channel().attr(id).get();
                        //do something with the idValue
                    }

                    @Override
                    protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf)
                            throws Exception {
                        System.out.println("Received data");
                    }
                });
        //设置ChannelOption其将在connect（）或者bind（）方法被调用时被设置到已经创建的Channel上
        bootstrap.option(ChannelOption.SO_KEEPALIVE,true)
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS,5000);
        //存储该id属性
        bootstrap.attr(id,123456);
        ChannelFuture future = bootstrap.connect(new InetSocketAddress("www.myself.com",80));
        future.syncUninterruptibly();*/

        /*//创建一个Bootstrap的实例以创建和绑定新的数据报Channel
        Bootstrap bootstrap = new Bootstrap();
        //设置EventLoopGroup,其提供了用以处理Channel事件的EventLoop
        bootstrap.group(new OioEventLoopGroup()).channel(OioDatagramChannel.class).handler(
                new SimpleChannelInboundHandler<DatagramPacket>() {
                    @Override
                    protected void channelRead0(ChannelHandlerContext channelHandlerContext,
                                                DatagramPacket datagramPacket) throws Exception {
                        //Do something with the packet
                    }
                }
        );
        //调用bind（）方法，因为该协议是无连接的
        ChannelFuture future = bootstrap.bind(new InetSocketAddress(0));
        future.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture channelFuture) throws Exception {
                if (channelFuture.isSuccess()){
                    System.out.println("Channel bound");
                } else {
                    System.out.println("Bind attempt faild");
                    channelFuture.cause().printStackTrace();
                }
            }
        });*/


        /*EventLoopGroup group = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group)
                .channel(NioSocketChannel.class);
        ...
        //shutdownGracefully()方法将释放所有的资源，并且关闭所有的当前正在使用中的Channel
        io.netty.util.concurrent.Future future = group.shutdownGracefully();
        //block until the group has shutdown
        future.syncUninterruptibly();*/
    }

    //用以设置ChannelPipeline的自定义ChannelInitializerImpl实现
    final static class ChannelInitializerImpl extends ChannelInitializer<Channel>{
        @Override
        protected void initChannel(Channel channel) throws Exception {
            ChannelPipeline pipeline = channel.pipeline();
            pipeline.addLast(new HttpClientCodec());
            pipeline.addLast(new HttpObjectAggregator(Integer.MAX_VALUE));
        }
    }

}
